package com.ylz.sjzx.sio.sdk.client.engine;

import cn.hutool.core.util.StrUtil;
import com.ylz.sjzx.sio.common.core.constant.Const;
import com.ylz.sjzx.sio.common.core.enums.Cmd;
import com.ylz.sjzx.sio.common.core.enums.Role;
import com.ylz.sjzx.sio.sdk.client.core.IMNioBase;
import com.ylz.sjzx.sio.sdk.client.session.IMSession;
import com.ylz.sjzx.sio.sdk.model.ChatRoomMessage;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * @author wiqi
 * @version 1.0
 * @date 2020/12/2
 */
public abstract class ChatEngine {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /**
     * 聊天室Id
     */
    protected String chatRoomId;
    /**
     * 组ID ,组消息
     */
    protected Map<String, Object> sunGroup = new HashMap<>(16);

    public ChatEngine(String chatRoomId) {
        this.chatRoomId = chatRoomId;
    }

    /**
     * 通过角色 总能获取对的角色
     *
     * @param chatRoomGroupId
     * @param role
     * @return
     */
    public Object alwaysGetSunGroupByRole(String chatRoomGroupId, Role role) {
        //非学生
        if (!Objects.equals(Role.st, role)) {
            chatRoomGroupId = Const.ADMIN;
        }
        return this.alwaysGetSunGroup(chatRoomGroupId);
    }

    public void removeGroup(String chatRoomGroupId) {

        Object remove = this.sunGroup.remove(chatRoomGroupId);
        if (remove == null) {
            this.logger.warn("该聊天室的{}用户组已经移除{}", this.chatRoomId, chatRoomGroupId);
        }
    }

    /**
     * 总能获取到用户组
     *
     * @param chatRoomGroupId
     * @return
     */
    public Object alwaysGetSunGroup(String chatRoomGroupId) {
        if (StrUtil.isBlank(chatRoomGroupId)) {
            chatRoomGroupId = "defaultGroup";
        }
        ChannelGroup channelGroup = (ChannelGroup) this.sunGroup.get(chatRoomGroupId);

        //这段保障总能获取唯一的用户组 防止并发
        if (channelGroup == null) {
            synchronized (chatRoomGroupId.intern()) {
                //锁chatRoomGroupId 的缓冲池常量
                channelGroup = (ChannelGroup) this.sunGroup.get(chatRoomGroupId);
                if (channelGroup == null) {
                    channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
                    this.sunGroup.put(chatRoomGroupId, channelGroup);
                }
            }
        }
        return channelGroup;
    }

    /**
     * togroup 为null 全体广播
     * <p>
     * 其他的根据组ID 跟是否toAdmin 发送
     *
     * @param chatRoomMessage
     */
    public long sendMessage(ChatRoomMessage chatRoomMessage) {
        long channleSize = 0;

        if (StrUtil.isBlank(chatRoomMessage.getToGroupName())) {
            //广播全体
            //群发
            Collection<Object> channelGroups = this.sunGroup.values();
            for (Object object : channelGroups) {
                ChannelGroup sunGroupItem = (ChannelGroup) object;
                channleSize += sunGroupItem.size();
                this.sendMsg(sunGroupItem, chatRoomMessage);
            }

        } else {
            //组用户发送
            ChannelGroup channelGroup =
                    (ChannelGroup) this.alwaysGetSunGroup(chatRoomMessage.getToGroupName());
            channleSize += channelGroup.size();
            this.sendMsg(channelGroup, chatRoomMessage);
            //needTeacherGetMsg 测试用的 可以设置不让老师收到消息
            boolean needTeacherGetMsg = IMNioBase.isNeedTeacherGetMsg();
            if (!needTeacherGetMsg) {
                needTeacherGetMsg = (!Objects.equals(Cmd.getMsg, chatRoomMessage.getCmd()));
            }
            if (chatRoomMessage.isToAdmin() && needTeacherGetMsg) {
                //向管理组发送
                ChannelGroup adminGroup = (ChannelGroup) this.alwaysGetSunGroup(Const.ADMIN);
                channleSize += adminGroup.size();
                this.sendMsg(adminGroup, chatRoomMessage);
            }
        }
        return channleSize;
    }

    /**
     * 将用户添加如聊天组
     */
    public ChatEngine add2ChatRoomGroup(IMSession session) {
        ChannelGroup sunGroup =
                (ChannelGroup) this.alwaysGetSunGroupByRole(session.getGroupName(), session.getRole());
        sunGroup.add(session.getChannel());
        this.logger.debug("加入组{},用户{}", session.getGroupName(), session.getSid());
        this.logger.debug("sunGroup{}", sunGroup);
        return this;
    }

    /**
     * 将用户从聊天室移除
     */
    public void removeFromChatRoomGroup(IMSession session) {
        ChannelGroup channelGroup = (ChannelGroup) alwaysGetSunGroup(session.getGroupName());
        if (session.getChannel() != null) {
            channelGroup.remove(session.getChannel());
        }
    }

    /**
     * 将用户添加如聊天组
     *
     * @param channelGroup
     * @param chatRoomMessage
     * @return
     */
    public abstract void sendMsg(ChannelGroup channelGroup, ChatRoomMessage chatRoomMessage);

}
